package config

import (
	"fmt"
	"time"

	log2 "log"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"xorm.io/xorm"
	"xorm.io/xorm/log"

	_ "github.com/mattn/go-sqlite3"
)

type Config struct {
	Server   ServerConfig
	Database DatabaseConfig
	JWT      JWTConfig
	Log      LogConfig
	CRUD     CRUDConfig
}

type ServerConfig struct {
	Port             int
	IncludeOriginUrl bool
}

type DatabaseConfig struct {
	Path string
}

type JWTConfig struct {
	Secret string
	Expire int
}

type LogConfig struct {
	Level        string
	Path         string
	MaxAge       int
	RotationTime int
}

type CRUDConfig struct {
	MaxPageSize     int `mapstructure:"maxPageSize"`
	DefaultPageSize int `mapstructure:"defaultPageSize"`
}

var (
	globalConfig *Config
	globalLogger *zap.Logger
)

func LoadConfig(configFile string) (*Config, error) {
	viper.SetConfigFile(configFile)
	viper.SetConfigType("toml")

	if err := viper.ReadInConfig(); err != nil {
		return nil, fmt.Errorf("failed to read config: %v", err)
	}

	var config Config
	if err := viper.Unmarshal(&config); err != nil {
		return nil, fmt.Errorf("failed to unmarshal config: %v", err)
	}

	globalConfig = &config

	// 初始化日志
	logger, err := InitLogger(&config.Log)
	if err != nil {
		return nil, fmt.Errorf("failed to init logger: %v", err)
	}
	globalLogger = logger

	// 替换标准库log
	zap.RedirectStdLog(globalLogger)

	viper.WatchConfig()
	viper.OnConfigChange(func(e fsnotify.Event) {
		log2.Println("Config file changed:", e.Name)
	})

	return &config, nil
}

func GetConfig() *Config {
	return globalConfig
}

func GetLogger() *zap.Logger {
	return globalLogger
}

func InitDB(cfg *Config) (*xorm.Engine, error) {
	engine, err := xorm.NewEngine("sqlite3", cfg.Database.Path)
	if err != nil {
		return nil, fmt.Errorf("failed to create database engine: %v", err)
	}

	engine.SetMaxOpenConns(10)
	engine.SetMaxIdleConns(5)
	engine.SetConnMaxLifetime(time.Hour)

	// 设置XORM日志输出到zap
	logger := GetLogger()
	engine.SetLogger(&XormZapLogger{logger: logger.With(zap.String("module", "xorm"))})
	engine.ShowSQL(true)

	if err := engine.Ping(); err != nil {
		return nil, fmt.Errorf("failed to ping database: %v", err)
	}

	return engine, nil
}

// XormZapLogger 实现xorm的logger接口
type XormZapLogger struct {
	logger *zap.Logger
}

func (l *XormZapLogger) Debug(v ...interface{}) {
	l.logger.Debug(fmt.Sprint(v...))
}

func (l *XormZapLogger) Debugf(format string, v ...interface{}) {
	l.logger.Debug(fmt.Sprintf(format, v...))
}

func (l *XormZapLogger) Error(v ...interface{}) {
	l.logger.Error(fmt.Sprint(v...))
}

func (l *XormZapLogger) Errorf(format string, v ...interface{}) {
	l.logger.Error(fmt.Sprintf(format, v...))
}

func (l *XormZapLogger) Info(v ...interface{}) {
	l.logger.Info(fmt.Sprint(v...))
}

func (l *XormZapLogger) Infof(format string, v ...interface{}) {
	l.logger.Info(fmt.Sprintf(format, v...))
}

func (l *XormZapLogger) Warn(v ...interface{}) {
	l.logger.Warn(fmt.Sprint(v...))
}

func (l *XormZapLogger) Warnf(format string, v ...interface{}) {
	l.logger.Warn(fmt.Sprintf(format, v...))
}

func (l *XormZapLogger) Level() log.LogLevel {
	return log.LOG_INFO
}

func (l *XormZapLogger) SetLevel(level log.LogLevel) {
	// 可以根据需要实现级别设置
}

func (l *XormZapLogger) ShowSQL(show ...bool) {
	// 可以根据需要实现SQL显示控制
}

func (l *XormZapLogger) IsShowSQL() bool {
	return true
}
